home *** CD-ROM | disk | FTP | other *** search
- #include "tmp/libpq.h"
- #include <stdio.h>
-
- #define LL 1000 /* upper limit on length of a data line */
- #define VPL '{' /* left hand side of a var in template */
- #define VPR '}' /* right hand side of var in template */
- #define MAX_COL 99 /* max number of columns per data line
- if MAX_COL is larger than 99, fix code in
- pg_process_data_file to handle more than 2 digits */
- #define NULL_CHAR '&'
-
-
- /**********************************************************************
- $Header: /private/postgres/src/contrib/3M/RCS/pg_exec.c,v 1.3 1991/05/15 08:37:17 mao Exp $
- **********************************************************************
- FILE: pg_exec.c
- pg_exec [-c | -d] databasename filename
-
- Author: Steve Anastasi, 3M, 612-733-6970
- smanastasi@mmm.serc.3m.com
-
-
-
- Date: 6-29-90
-
- Processes ascii files as postgres commands. This program takes
- a two arguments - a database name, and a filename or pathname
- of an ascii file. The database must already exist.
- Two options are available:
-
- -c Process the ascii file as a sequence of postgres
- commands. This is the default. See the format of a
- postgres command file below.
-
- -d Process the ascii file as data file. Data in the file is
- imported according to a specification contained on the
- first line of the file. See the format of a import file
- below.
-
- Command file format:
- --------------------
- Each line is simply a postgres command that can be executed
- directly using PQexec. Using pg_exec -c <filename> has the
- same effect as using the terminal monitor interface and
- including the filename (\i filename).
-
- It is important that each postgres command is entirely
- contained on a single line and the each line is deliminated by
- a newline or return character.
-
- Import file format:
- -------------------
- An import file is composed of two sections. The first section
- is the first line of the file. It specifies the postgres
- command that should be used to add the data to the database.
- This is called the command template.
-
- The second section is the rest of the file. Each line is a
- tab-deliminated record containing data. Special tokens ({num})
- in the command template specify the column of data that should be
- used. An example follows.
-
- append somerel (name={0}::text, id={1}, gpa={2}::float4)
- "David Byrne" 154323 "3.00"
- "Phillip E. Bach" 000321 "3.93"
- "Ronald Reagan" 000000 "0.00"
- "Cole Porter" 103423 "2.45"
-
- Note that each field is tab-delimited and each value must be in
- the proper syntax so it can be dropped right in for its {#}.
-
- In addition, no null values can be specified in a dataline by
- \tab\tab or any other trick. For example, if {7} is the
- largest number (7) in the command template, then there must be
- 8 values (0,1,2,...,7) on every line of data.
- */
-
-
- /**********************************************************************
- pqexec_ret
-
- Looks at first character of the string returned by pqexec. If
- there is an error, -1 is returned, else 1 is returned.
- */
- int pqexec_ret (s)
- char *s;
- {
- if (s[0] == 'R')
- return(-1);
- else
- return(1);
- }
-
-
-
-
-
- /**********************************************************************
- Read a text string from an ascii file. A text string is defined as
- text deliminated by either a tab, newline or return character.
- In the process of reading a string, the file pointer gets advanced.
- Note that spaces do not deliminate strings.
- */
-
- void get_string(fptr, string_buffer)
- FILE *fptr;
- char *string_buffer;
- {
- int i;
-
- i = 0;
- if ((string_buffer[i] = getc(fptr)) != EOF) {
- while (string_buffer[i] != EOF &&
- string_buffer[i] != '\t' &&
- string_buffer[i] != '\n' &&
- string_buffer[i] != '\r') {
- i = i+1;
- string_buffer[i] = getc(fptr);
- }
- }
- /* Now replace the last character with a null terminater */
- string_buffer[i] = '\0';
- }
-
-
- /**********************************************************************
- Read a line from a text file. A line is defined as any character
- string that ends in \n . Returns a ptr to a null terminated string
-
- NOT CURRENTLY USED. USE GET_STRING INSTEAD IF POSSIBLE
- */
-
- char * readline(fptr)
- FILE *fptr;
- {
- char buffer[LL];
- int i;
-
- i = 0;
- buffer[i] = getc(fptr);
- while (buffer[i] != EOF && buffer[i] != '\n')
- buffer[++i] = getc(fptr);
- buffer[i] = '\0';
- return(buffer);
- }
-
-
- /*********************************************************************
- pg_process_data_file
-
- Reads formatted data from a ascii file and inserts the data into
- a postgres relation. One file can contain data for only one
- relation.
-
- File Format:
- The first line is a template to be used to specify how the data
- will get append to a relation. The token VPL and VPR indicates a place
- to drop in data from the data file. In each VP is a number
- indicating what field from a data line to use. (See top of file
- for definition of VPL and VPR.)
-
- Example:
- A datafile might look like:
-
- append parameter (name={0}::text, age={1}, weight={2}::float4)
- Steve Anastasi 26 190.04
- Saavik Stargazer 1 67.30
- etc.,
-
- Note that each field is tab delimited and each line ends in a newline
- or return character.
-
- Limitations: At most, MAX_COL data columns can be handled
- Every column in the data file must have a value
- */
-
-
- void pg_process_data_file(fptr)
- FILE *fptr;
-
- {
- char header[LL], command_string[LL*2], data[LL], tc;
- char var_num[3], tk[MAX_COL][LL];
- int i, h_ctr, c_ctr, token_count, var_val, EOF_REACHED;
-
- EOF_REACHED = 0;
- get_string(fptr, header);
- /* Find out how many data fields should be on each data line. This
- is done by finding the maximum number enclosed in VPL and VPR.
- The number of data fields is this number plus 1 (since counting
- starts at 0. */
- token_count = 0;
- i = 0;
- while (header[i] != '\0') {
- if (header[i] == VPL) {
- /* see if there is one or two digits after VPL */
- if (header[i+2] == VPR) { /* one digit */
- var_num[0] = '0';
- var_num[1] = header[i+1];
- var_num[2] = '\0';
- }
- else if (header[i+3] == VPR) { /* 2 digits */
- var_num[0] = header[i+1];
- var_num[1] = header[i+2];
- var_num[2] = '\0';
- }
- else { /* problem */
- printf("Error in data file. Unknown { } syntax\n");
- abort();
- }
- sscanf(var_num, "%d", &var_val);
- if (var_val > token_count)
- token_count = var_val;
- }
- i = i+1;
- }
-
- /* Iterate thru all data lines */
- while (!EOF_REACHED) {
- /* Now get as many strings from the data file as specified by
- token count */
- for (i=0;i<=token_count;i++) {
- get_string(fptr, tk[i]);
- if (tk[i][0] == '\0')
- EOF_REACHED = 1;
- }
-
- /* Now start to copy header into command_string, and replace
- {x} with tk[x] */
- h_ctr = 0;
- c_ctr = 0;
- while (header[h_ctr] != '\0' && c_ctr < LL*2 && !EOF_REACHED) {
- /* printf("H[%d]: %c\nC: %s\n",h_ctr,header[h_ctr],command_string); */
- if (header[h_ctr] == VPL) {
- /* see if there is one or two digits after VPL */
- if (header[h_ctr+2] == VPR) { /* one digit */
- var_num[0] = '0';
- var_num[1] = header[h_ctr+1];
- var_num[2] = '\0';
- h_ctr = h_ctr + 3; /* advance to after VPR */
- }
- else if (header[h_ctr+3] == VPR) { /* 2 digits */
- var_num[0] = header[h_ctr+1];
- var_num[1] = header[h_ctr+2];
- var_num[2] = '\0';
- h_ctr = h_ctr + 4; /* advance to after VPR */
- }
- else { /* problem */
- printf("Error in data file. Unknown { } syntax\n");
- abort();
- }
- sscanf(var_num, "%d", &var_val);
-
- /* now splice in tk[var_val] to command_string */
- i = 0;
- while (*(tk[var_val]+i) != '\0') {
- command_string[c_ctr] = *(tk[var_val]+i);
- i = i+1;
- c_ctr = c_ctr+1;
- }
- } /* header[h_ctr] == VPL */
- else { /* just copy from header to command string */
- command_string[c_ctr] = header[h_ctr];
- h_ctr = h_ctr + 1;
- c_ctr = c_ctr + 1;
- }
- }
- if (!EOF_REACHED) {
- /* Now execute the query */
- command_string[c_ctr] = '\0';
- printf("Exec: %s\n", command_string);
- if (pqexec_ret(PQexec(command_string)) < 0)
- printf("*Error* %s\n", command_string);
- }
- } /* end while not EOF_REACHED */
- printf("\n");
- }
-
-
- /*******************************************************************
- pg_process_command_file
-
- Reads a ascii file of postgres commands and executes them. Each
- command must be on a single line.
- */
-
- void pg_process_command_file(fptr)
- FILE *fptr;
-
- {
- char command[255];
- int EOF_REACHED;
-
- EOF_REACHED = 0;
-
- while (!EOF_REACHED) {
- get_string(fptr, command);
- if (command[0] == '\0')
- EOF_REACHED = 1;
- else {
- printf("Exec: %s\n", command);
- if (pqexec_ret(PQexec(command)) < 0)
- printf("*Error* %s\n", command);
- }
- }
- printf("\n");
- }
-
-
-
- /******************************************************************* */
- main (argc, argv)
- int argc;
- char *argv[];
-
- {
- FILE *fopen(), *fptr;
- char db_name[16],filename[80], *s, option;
- int place, j, error; /* error: -1= bad command line, -2=bad file, -3=bad */
- /* db name */
-
- error = 0;
- /* check for bad command line */
- if (argc < 3)
- error = -1;
- else if (argc==3 && (argv[1][0] == '-' || argv[2][0] == '-'))
- error = -1;
- else if (argc==4 && (argv[1][0] != '-' || argv[2][0] == '-' ||
- argv[3][0] == '-'))
- error = -1;
- else if (argc > 4)
- error = -1;
-
- if (error == -1) {
- printf("Usage: pg_exec [-c | -d] dbname filename\n");
- exit(-1);
- }
-
- /* get the option */
- if (argv[1][0] == '-')
- option = argv[1][1];
- else
- option = 'c'; /* the default */
-
- /* get the database */
- if (argv[1][0] == '-')
- place = 2;
- else
- place = 1;
-
- j = 0;
- while (argv[place][j] != '\0' && j < 16) {
-
- db_name[j] = argv[place][j];
- j = j + 1;
- }
-
- j =0;
- /* get file name */
- place = place +1;
- while (argv[place][j] != '\0' && j < 80) {
- filename[j] = argv[place][j];
- j = j + 1;
- }
-
-
- /* Now do the right thing */
-
- PQsetdb(db_name);
-
- printf("*Database: %s\n", PQdb());
-
- fptr = fopen(filename, "r");;
- if (fptr == (FILE *) NULL) {
- printf("Had problem opening %s.\n", filename);
- exit(-1);
- }
-
- if (option == 'c')
- pg_process_command_file(fptr);
- else if (option == 'd')
- pg_process_data_file(fptr);
-
- close (fptr);
- }
-
-
-